<?php
/**
 *
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *
 * @copyright Copyright (c) 2003-2009, Nogaide BootStrap INC. All rights reserved.
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 *
 */

/**
 * @namespace
 */
namespace X;

/**
 *
 * Simple class loader
 *
 *
 */
class Loader
{
    /**
     * register this class using the SPL Autoload Register
     * @return bool
     */
    static public function registerAutoload()
    {
        spl_autoload_register(__CLASS__ . '::autoload');
        return true;
    }
    /**
     * traverse names to autoload
     * @param string $name
     * @return bool
     */
    static public function autoload($name)
    {
        static $trace_depth = 0;
        $success = false;
        // track autoload fire
        self::log('Autoload call level ' . ++$trace_depth . " - $name");
        
        // make a clean file name
        $load_name = self::simplePath($name);
        // try to resolve the simple file name
        $resolved = stream_resolve_include_path($load_name . '.php');
        
        // trace the file name
        self::log($load_name . ' found: ' . $resolved);
        
        // include if successfully resolved
        if ($resolved)
        {
            $success = include $resolved;
        }
        else
        {
            // try to resolve and include using the current namespace
            $load_name = self::simplePath(__NAMESPACE__ . DIRECTORY_SEPARATOR . $name);
            $resolved = stream_resolve_include_path($load_name . '.php');
            self::log($load_name . ' found: ' . $resolved);
            
            if ($resolved)
            {
                $success = include $resolved;
            }
        }
        
        // log and return
        self::log('<< ' . $trace_depth--);
        return $success;
    }
    /**
     * create a simple class path with normalized delimiters
     * @param string $name
     * @return string
     */
    static public function simplePath($name)
    {
        return str_replace(array('\\', '_'), \DIRECTORY_SEPARATOR, $name);
    }
    /**
     * Add a path to the include path
     * @param string $path
     * @return string|bool false if the path is not found
     */
    static public function addIncludePath($path)
    {
        $pathToX = realpath($path);
        
        if ($pathToX)
        {
            set_include_path($pathToX . PATH_SEPARATOR . get_include_path());
        }
        
        return $pathToX;
    }
    /**
     *
     * @param string $ClassName
     * @param string $PathName
     * @return bool
     */
    static public function loadFile($ClassName, $PathName)
    {
        $ActualPath = \realpath(self::cleanSlashes($PathName . $ClassName) . '.php');
        if ($ActualPath)
        {
            include $ActualPath;
            return true;
        }
        return false;
    }
    /**
     * loads a class via specified specified path or global search path
     *
     * @param string $ClassName
     * @param string $Path
     * @return bool
     */
    static public function loadClass($ClassName, $Path = null)
    {
        if (empty($Path))
        {
            return class_exists($ClassName, true);
        }
        else
        {
            self::loadFile($ClassName, $Path);
            return class_exists($ClassName, false);
        }
    }
    
    static public function cleanSlashes($path)
    {
        return str_replace('\\', '/', $path);
    }
    /**
     * allow printing of errors and messages
     *
     * @var bool
     */
    static protected $_Debug = false;
    /**
     * trace of controller debug information
     *
     * @var \X\Logger
     */
    static protected $_Logger;
	/**
     * enable debuging mode
     * @return bool
     */
    static public function isDebug($Debug = null, \X\Logger $Logger = null)
    {
        // reset debug if it is passed
        self::$_Debug = ($Debug == null) ? true : (bool)$Debug;
        
        // set logger if debug is true
        if (self::$_Debug)
        {
            if ($Logger == null)
            {
                require_once 'Logger.php';
                require_once 'Logger/Memory.php';
                self::$_Logger = \X\Logger\Memory::getInstance('loader');
            }
            else
            {
                $this->_Logger = $Logger;
            }
        }
        
        // return the value of logger
        return self::$_Debug;
    }
    /**
     * log a message
     * @param string $Message
     * @param string $Type
     */
    static protected function log($Message, $Type = 'general')
    {
        if (self::$_Debug && self::$_Logger) self::$_Logger->logMessage($Message, $Type);
    }
}